#######################################################
# Example of FSDEVS network model for a two gun fithers 
# FSDEVS stands for Finite (states & events) and Stochastic behaviors 
#  in terms of state transitions, output, and time advance. 
# Author: moonho.hwang@gmail.com
#   Date: Oct.20.2011
#######################################################
from XSY.DEVS.FSDEVS import * 

from XSY.DEVS.CoupledDEVS import *
from XSY.Set.Interval import *

from XSY.DEVS.SimEngine import SimEngine
from XSY.DEVS.VeriEngine import VeriEngine

class GunFighter(FSDEVS):
   ''' an atomic FSDEVS of a gun fighter'''
   def __init__(self, n, sintv, sp, parent=None):
      '''constructor'''
      if sp>=1: raise Exception("%f should be in (0,1)"%sp)
      # make the base class FSDEVS
      FSDEVS.__init__(self, n, parent) 

      self.sintv = sintv
      self.sp = sp

      # make ports  
      self.addInputPorts('?r')
      self.addOutputPorts('!s')
      self.addOutputPorts('!m')

      # make vertices
      #self.G.addVtx('S', {S_rv_ta:sintv}); 
      #self.G.addVtx('A', {S_rv_ta:float('inf')}); 
      #self.G.addVtx('D', {S_rv_ta:float('inf')}); 

      # make edges
      #self.G.addEdge('S', 'A', {'y':PortValue(self.OP['!s']), S_p:sp })
      #self.G.addEdge('S', 'A', {'y':PortValue(self.OP['!m']), S_p:1-sp })
      #self.G.addEdge('S', 'D', {'x':self.IP['?r']})
      #self.G.addEdge('A', 'D', {'x':self.IP['?r']})

   def rv_delta_0(m):
      '''random initial state'''
      return DRV({'S':1})

   def rv_tau(m):
      '''random lifespan scheduling function'''
      if m.phase == 'S':
         if isinstance(m.sintv, TInterval):
            return m.sintv # this one is interval
         else:
            return DRV({m.sintv:1})
      else:
         return DRV({float('inf'):1})

   def rv_delta_x(m, x):
      '''random external transition function'''
      return DRV({(True,'D'):1})

   def rv_delta_y(m):
      '''random output and internal transition function'''
      if m.phase == 'S':
         return DRV({ (PortValue(m.OP['!s']),'A'):m.sp, (PortValue(m.OP['!m']), 'A'):1-m.sp })
      else:
         return DRV({(None,m.phase):1})

   def get_state(m):
      '''get the state'''
      return m.phase

   def set_state(m, s):
      '''set the state as s'''
      m.phase = s

 
def makeModel():
   print 'This example shows a coupled model "system" having two gun-fighters "g1" and "g2" '

   md1 = GunFighter("g1", TInterval(.2, .5), .99) 
   md2 = GunFighter("g2", TInterval(.1, .4), .90) 
   cm = CoupledDEVS("", )
   cm.addComponents(md1, md2)

   cm.addCouple(md1.OP["!s"], md2.IP["?r"])
   cm.addCouple(md2.OP["!s"], md1.IP["?r"])
   return cm


def runSimulation(md):
   engine = SimEngine(md)

   #---- setting StepByStep and DES simulation only ----
   #engine.StepByStep = True
   engine.sfactor = float('inf')
   #----------------------------------------------------
   engine.runInteractiveMenu()

def runVerification(md):
   X = []
   #X.append(PortValue(md.IP['?stop']))
   VE = VeriEngine(md, X, None, None)
   VE.runtimeInteractiveMenu()

if __name__ == '__main__':
   md = makeModel()

   c = True
   while c:
      s = raw_input('[s]im, [v]eri, e[x]it>')
      if s == 's' or s == 'sim': 
         runSimulation(md)
      elif s == 'v' or s == 'veri':
         runVerification(md)
      elif s == 'x' or s == 'exit':
         c = False
      else:
         print('%s is an invalid input!'%s)
      
   print "good bye~!" 
